<?php
require ('lsamp_curl.php');
/**
 * HostmonsterClient
 *
 * This class will be used to manage domains of a hostmonster account
 * @package Hostmonster
 */
class HostmonsterClient{
	/**
	 * The array contain login domain and password
	 *
	 * @var array
	 */
	private  $dom_account = array(
			'dom' => '',
			'password' => ''
			);

			/**
			 * The url string of the login form
			 *
			 * @var string
			 */
			private $dom_manager_login_url;

			/**
			 * The url string used to checking domain
			 *
			 * @var string
			 */
			private $dom_check_url;

			/**
			 * The http client use to interact with the hostmonster
			 *
			 * @var lsamp_cURL http_client
			 */
			private $http_client;

			/**
			 * The error number of prvious action
			 *
			 * @var int errno
			 */
			private $errno;


			/**
			 * The error message of prvious action
			 *
			 * @var int error
			 */
			private $error;


			/**
			 * Function to set the dom_check_url value
			 *
			 * @param string $url the url to be set
			 */
			function set_dom_check_url($url){
				if($url !== ''){
					$this->dom_check_url = $url;
				}
			}

			/**
			 * Function to get the dom_check_url value
			 *
			 */
			function get_dom_check_url(){
				return $this->dom_check_url;
			}

			/**
			 * Function to set the dom_manager_login_url
			 *
			 * @param string $url the url to be set
			 */
			function set_dom_manager_login_url($url){
				if($url !== ''){
					$this->dom_manager_login_url = $url;
				}
			}

			/**
			 * Function to get the dom_manager_login_url
			 *
			 * @return string the dom_manager_login_url
			 */
			function get_dom_manager_login_url(){
				return $this->dom_manager_login_url = $url;
			}

			/**
			 * Get the domain account
			 *
			 * @return array the dom_account array
			 */
			function get_dom_account(){
				return $this->dom_account;
			}

			/**
			 * Set the domain account
			 *
			 * @param array $dom_account		 *
			 */
			function set_dom_account($dom_account){
				$this->dom_account = $dom_account;
			}

			/**
			 * Get the error number
			 *
			 * @return errno
			 */
			function get_error_number(){
				return $this->errno;
			}

			/**
			 * Get the error message
			 *
			 * @return error
			 */
			function get_error_message(){
				return $this->error;
			}

			/**
			 * Constructor
			 *
			 * @param string $dom the domain to login
			 * @param string $password the password of the domain
			 * @param string $dom_manager_login_url the url used login the domain manager page
			 * @param string $dom_check_url the url used to check whether a domain exists.
			 */
			function HostmonsterClient($dom, $password, $dom_manager_login_url, $dom_check_url = ''){
				if($dom == ''){
					die('The domain to login must be provided');
				}
				$this->dom_account['dom'] = $dom;
				if($password == ''){
					die('The domain password must be provided');
				}
				$this->dom_account['password'] = $password;
				if($dom_manager_login_url == ''){
					die('The domain manager login url must be provided');
				}else{
					$this->dom_manager_login_url = $dom_manager_login_url;
				}
				if($dom_check_url == ''){
					die('The domain checking url must be provided');
				}else{
					$this->dom_check_url = $dom_check_url;
				}
				// setup the http client
				$this->http_client = new lsamp_cURL(TRUE, 'cookies.dat', 'gzip', '', 'https://www.hostmonsterdemo.com', 30);
			}

			/**
			 * Login the domain manager
			 *
			 * @return true|false if successfully logged in, if failed set errno and error message
			 *
			 */
			function login_domain_manager(){
				$login_data = "l_redirect=/cgi/hosting"
				. "&l_expires_min=0"
				. "&ldomain=" . $this->dom_account['dom']
				. "&lpass=" . $this->dom_account['password'];
				$result = $this->http_client->post($this->dom_manager_login_url, $login_data, $this->errno, $this->error);
				if($this->errno != 0){
					return false;
				}else{
					if(strstr($result, "Login Failed") !== false){
						$this->error = 'Wrong domain/password or login url, can\'t login the domain manager';
						return false;
					}else{
						return true;
					}

				}
			}

			/**
			 * This function get the domain list of the given account
			 *
			 * @param string &$msg the output message
			 * @return NULL|array NULL if there is no domain or there is an error occurred
			 */
			function get_domain_list(&$msg){
				$dom_list = array();
				// get html page
				$html = $this->http_client->get($this->dom_manager_login_url,$this->errno, $this->error);
				if($this->errno != 0){
					$msg = $this->error;
					return NULL;
				}else{
					//				if(!preg_match_all('#<td class="hcol_1"><div>([^<]+)</div>#mis',$html, $name_match_array)){
					//					$this->error = "Failed to get domain list, the site changed its format";
					//					return NULL;
					//				}else{
					//					for($i=1; $i < count($name_match_array[1]); $i++){
					//						array_push($dom_list, $name_match_array[1][$i]);
					//					}
					//					return $dom_list;
					//				}
					if(!preg_match_all('#<tr class="(?:even|odd|(?:odd last)|(?:even last))">(?:.(?!</tr>))+#mis', $html, $matches)){
						$msg = "Failed to get domain list, the site changed its output format";
						return NULL;
					}else{
						foreach($matches[0] as $match){
							foreach($matches[0] as $match){
								if(preg_match_all('#>([^<\n]+)<#mis', $match, $matches_l2)){
									$dom = array();
									$dom['name'] = $matches_l2[1][0];
									$dom['status'] = $matches_l2[1][1];
									array_push($dom_list, $dom);
								}
							}
						}
						$msg = "Success";
						return $dom_list;
					}

				}
			}

			/**
			 * Check whether a domain belongs to hostmonster
			 *
			 * @param string $dom_to_check the domain name to check
			 * @param string &$msg the return message
			 * @return true|false true if the domain is currently pointing to the hostmonster
			 */

			function check_dom($dom_to_check, &$msg){
				$check_domain_data = "domain=" . $dom_to_check;
				$html = $this->http_client->post($this->dom_check_url, $check_domain_data, $this->errno, $this->error);
				if($this->errno != 0){
					$msg = $this->error;
					return false;
				}else{
					if(preg_match('/\(\{([^{]+)\}\)/mis', $html, $matches)!==false){
						$parts = split("\",\"",$matches[1]);
						if(count($parts) > 1){
							//the second part is the owner_type
							$owner_part = split("\":\"", $parts[1]);
							//the first part is the message
							$msg_part = split("\":\"", $parts[0]);
							$msg = str_replace("\"", "", $msg_part[1]);
							$msg = str_replace("\\\"", "", $msg_part[1]);
							if(($tmp = preg_replace('/(<[^>]+>)/mis','',$msg)) != NULL){
								$msg = $tmp;
							}
							$owner_type = str_replace("\"", "", $owner_part[1]);
							if($owner_type == "epp"){
								return false;
							}else{
								if(preg_match('/(unassigned|dns|embedded_code|call)/', $owner_type, $matches)){
									return true;
								}
							}
							return false;
						}else{
							$msg_part = split("\":\"", $parts[0]);
							$msg = str_replace("\"", "", $msg_part[1]);
							$msg = str_replace("\\\"","", $msg);
							return false;
						}
					}else{
						$msg = "Failed to check domains, the hostmonster.com site changed its output format";
						return false;
					}
				}
			}

			/**
			 * Add domain function
			 *
			 * @param string $dom_type the domain type to add, there are two acceptable value local|other
			 * @param string $dom the domain to add
			 * @param string $owner_code domain owner code(epp code)
			 * @param string $assign_type the assign type, there are two valid values addon|parked
			 * @param string $assign_dir the directory to assign
			 * @param string $dom_sub the subdomain to use with the addon
			 * @param string &$msg output message
			 *
			 * @return true|false true if added, false otherwise		 *
			 */
			function add_dom( $dom, $dom_type='other', $owner_code, $assign_type, $assign_dir, $dom_sub, &$msg){
				$success_message = "You are working on the demo account.  The options you have selected appear to be in working order, but the domain will not be assigned because you are on the demo account.";
				$error_messages = array(
					//invalid epp code message
					"Invalid EPP authorization code",
					//subdomain missing message
					"Please type a sub-domain to use for your addon",
					//assign directory missing message
					"Please type a directory name",
					//no more un-assigned message
					"No more un-assigned domain available",
					// directory name format
					"New directories may only contain letters, numbers dashes and periods",
					// addon slection
					"Please select whether the domain will be an Addon or Parked domain",
					// addon directory
					"Addon directories may only contain letters, numbers dashes and periods",
					// domain name prefix
					"Please type the domain without the www. prefix.",
					// domain slect
					"Please select a valid domain",
					// new subdomain
					"New sub-domains may only contain letters and numbers"
				);

				//post data
				$add_domain_data = "step=assign"
				."&domain_type=" . $dom_type
				. "&domain=" . $dom
				. "&assign_type=" . $assign_type;
				if($owner_code == ''){
					$add_domain_data .= "&owner=n/a";
				}else{
					$add_domain_data .= "&owner=" . $owner_code;
				}
				// if the assign type is addon, we add the assign directory information
				if($assign_type == "addon"){
//					if($subdom == ''){
//						$msg = $subdom_missing;
//						return false;
//					}
//					if($dir == ''){
//						$msg = $dir_missing;
//						return false;
//					}
					$add_domain_data .= "&dir_type=new"
					."&dir=" . $assign_dir
					."&sub=" . $dom_sub;
				}
				$html = $this->http_client->post($this->dom_manager_login_url, urldecode($add_domain_data), $this->errno, $this->error);
				if($this->errno != 0){
					// curl error
					$msg = $this->error;
					return false;
				}else{
					if(strstr($html, $success_message)){ // contain success message
						$msg = $success_message;
						return true;
					}else{
						preg_match('#<form((?:.(?!</form>))+)#mis', $html, $matches);
						$form = $matches[1];
						foreach($error_messages as $error_message){
							if(strstr($form, $error_message)){
								$msg = $error_message;
								return false;
							}
						}
						//assign form to msg
						$msg = $form;
						return false;
					}
				}
		}

		/**
		 * This function is used to unassign a domain
		 *
		 * @param string $dom domain to unassign
		 * @param string $msg the output message
		 * @return true|false
		 */
		function unassign($dom, &$msg){
			$dom = trim($dom, " ");
			//need review --> this success message
			$success_message = "Successfully unassigned domain " . $dom;
			$error_messages= array(
				"The domain " . $dom . " is currently not attached to a cPanel account."
			);
			$unassign_data = "step=unassign"
							. "&domain=" . $dom
							. "&confirm=Un-assign the domain " . $dom;
			$html = $this->http_client->post($this->dom_manager_login_url, $unassign_data , $this->errno, $this->error);
			if($this->errno != 0){
				// curl error
				$msg = $this->error;
				return false;
			}else{
				if(strstr($html, $success_message) !== false){
					$msg = $success_message;
					return true;
				}else{
					foreach($error_messages as $error_message){
						if(strstr($html, $error_message)){
							$msg = $error_message;
							return false;
						}
					}
					$msg = $html;
					return false;
				}
			}

		}

		/**
		 * This function is used to remove a domain
		 *
		 * @param string $dom domain to remove
		 * @param string $msg the output message
		 * @return true|false
		 */
		function remove($dom, &$msg){
			$dom = trim($dom, " ");
			$success_message = "Successfully removed domain";
			$error_messages= array(
				"You are not the current owner of the domain " . $dom,
				"The domain " . $dom ." must be un-assigned before you may remove it"
			);
			$remove_data = "step=remove"
							. "&domain=" . $dom
							. "&confirm=Remove the domain " . $dom;
			$html = $this->http_client->post($this->dom_manager_login_url, $remove_data , $this->errno, $this->error);
			if($this->errno != 0){
				// curl error
				$msg = $this->error;
				return false;
			}else{
				if(strstr($html, $success_message) !== false){
					$msg = $success_message . $dom;
					return true;
				}else{
					foreach($error_messages as $error_message){
						if(strstr($html, $error_message)){
							$msg = $error_message;
							return false;
						}
					}
					$msg = $html;
					return false;
				}
			}

		}

}


